package top.saplf.sileny.reader.shelf

import android.app.Activity
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.support.v7.widget.GridLayoutManager
import android.view.View
import cn.nekocode.rxlifecycle.compact.RxLifecycleCompact
import com.github.ajalt.timberkt.Timber
import com.jakewharton.rxbinding2.support.v4.widget.RxSwipeRefreshLayout
import com.nbsp.materialfilepicker.MaterialFilePicker
import com.nbsp.materialfilepicker.ui.FilePickerActivity
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_local_book_index.*
import top.saplf.sileny.R
import top.saplf.sileny.base.ui.SilenyMviFragment
import top.saplf.sileny.ext.*
import top.saplf.sileny.main.home.MainActivity
import java.io.File
import java.util.*
import java.util.regex.Pattern

/**
 * @author Saplf on 17/4/23
 */
class LocalBookIndexFragment :
        SilenyMviFragment<LocalBookIndexView, LocalBookIndexPresenter>(),
        LocalBookIndexView, IRxActivityResult<LocalBook> {

    companion object {

        fun getInstance() = LocalBookIndexFragment()
        private const val FILE_PICKER_REQUEST_CODE = 1

        private const val LAST_FILE_CHOOSE_PATH = "last path"
    }

    private val realm: Realm by lazy { Realm.getDefaultInstance() }

    private val progressDlg: ProgressDialog by lazy {
        ProgressDialog(context).apply {
            setMessage("正在导入")
            setTitle(R.string.importing)
        }
    }
    private val mAdapter by lazy {
        LocalBookIndexAdapter(listOf<LocalBook>().toMutableList()).apply {
            bindToRecyclerView(bookList)
        }
    }
    private var mActivityResultListener: ActivityResultListener<LocalBook>? = null

    override fun onLayoutRes()
            = R.layout.fragment_local_book_index

    override fun createPresenter(): LocalBookIndexPresenter
            = LocalBookIndexPresenter(LocalBookLoader())

    override fun loadFirstPageIntent(): Observable<Boolean>
            = Observable.just(true).doOnComplete { Timber.d { "first page finished" } }

    override fun loadNextPageIntent(): Observable<LocalBook>
            = RxActivityResult.bind(this)

    override fun pullToRefreshIntent(): Observable<Boolean>
            = RxSwipeRefreshLayout.refreshes(swipeRefresh).map { true }

    override fun render(viewState: LocalBookIndexViewState) {
        when (viewState) {
            is FirstPageLoadingViewState -> {
                mAdapter.setEmptyView(R.layout.view_loading)
            }
            is FirstPageErrorViewState -> {
                mAdapter.setEmptyView(R.layout.view_empty)
            }
            is PullToRefreshingViewState -> {
            }
            is PullToRefreshErrorViewState -> {
                swipeRefresh.isRefreshing = false
                (activity as MainActivity).loadErrorSnack.show()
            }
            is ReloadDataViewState -> {
                swipeRefresh.isRefreshing = false
                if (viewState.data.isEmpty()) {
                    mAdapter.setEmptyView(R.layout.view_empty)
                } else {
                    mAdapter.setNewData(viewState.data)
                }
            }
            is NextPageLoadingViewState -> {
            }
            is NextPageErrorViewState -> {
                (activity as MainActivity).loadErrorSnack.show()
            }
            is AppendDataViewState -> {
                swipeRefresh.isRefreshing = false
                mAdapter.addData(viewState.data)
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        with(bookList) {
            layoutManager = GridLayoutManager(context, 2)
            adapter = mAdapter
        }
        super.onViewCreated(view, savedInstanceState)
    }

    override fun onDestroy() {
        super.onDestroy()
        realm.close()
    }

    override fun setActivityResultListener(listener: ActivityResultListener<LocalBook>?) {
        mActivityResultListener = listener
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == FILE_PICKER_REQUEST_CODE &&
                resultCode == FilePickerActivity.RESULT_OK &&
                data != null) {
            val path = data.getStringExtra(FilePickerActivity.RESULT_FILE_PATH)
            val lastSeparator = path.lastIndexOf(File.separatorChar)
            cacheSharedPref.write {
                putString(LAST_FILE_CHOOSE_PATH, path.substring(0, lastSeparator))
            }
            progressDlg.show()
            val fileName = path.substring(lastSeparator + 1, path.length).splitFileName()
            val book = LocalBook(
                    id = UUID.randomUUID().toString(),
                    name = fileName.first,
                    path = path,
                    postfix = fileName.second
            )
            Observable.just(book)
                    .subscribeOn(AndroidSchedulers.mainThread())
                    .observeOn(Schedulers.io())
                    .doOnNext {
                        it.path = "${context.getDir("books", Context.MODE_PRIVATE).absolutePath}${File.separatorChar}${it.id}"
                        path.copyTo(it.path)
                    }
                    .observeOn(AndroidSchedulers.mainThread())
                    .compose(RxLifecycleCompact.bind(this).withObservable())
                    .subscribe({
                        progressDlg.dismiss()
                        mActivityResultListener?.onResult(it)
                    }, { it.printStackTrace() })
        }
    }

    fun actionClick(activity: Activity) {
        MaterialFilePicker()
                .withActivity(activity)
                .withRequestCode(FILE_PICKER_REQUEST_CODE)
                .withFilter(Pattern.compile(".*\\.txt$"))
                .withPath(cacheSharedPref.getString(LAST_FILE_CHOOSE_PATH, Environment.getExternalStorageDirectory().absolutePath))
                .withHiddenFiles(false)
                .start()
    }
}